import { isGenerateEqual } from '../utils/object-equal';
export function Transform() {
    return function (target: any) {

    }
}
type ToJsonOptions = {
    name?: string, 
    ignore?: boolean, 
    toObj?: (...args: any[]) => any, 
    toCls?: (instance: any, value: any) => any,
    parsePriority?: number;
}
export function toJSON(defaultValue: any, opt: ToJsonOptions = {}) {
    return function (target: any, propertyKey: string) {
        if (opt.name === undefined) {
            opt.name = propertyKey;
        }
        if (target.constructor.prototype.__TO_JSON_MAP__ === undefined) {
            Object.defineProperty(target, '__TO_JSON_MAP__', {
                enumerable: false,
                value: {}
            })
        }
        target.constructor.prototype.__TO_JSON_MAP__[opt.name] = {
            name: propertyKey,
            defaultValue: defaultValue,
            // opt: opt
            ...opt
        };
    }
}

export function classTransformToObj(cls: Object) {
    let map = cls.constructor.prototype.__TO_JSON_MAP__;
    let result: { [key: string]: any } = {};
    for (let key in map) {
        let fieldInfo = map[key];
        // @ts-ignore
        let value: any = cls[fieldInfo.name];
        if (isGenerateEqual(value,fieldInfo.defaultValue) || value === null || value === undefined) {
            continue;
        }
        if(fieldInfo.opt.toObj) {
            let temp = fieldInfo.opt.toObj(value, cls);
            if(temp === undefined) {
                continue;
            }
            if(!isGenerateEqual(temp,fieldInfo.defaultValue)) {
                result[key] = temp;
            }
        } else {
            result[key] = value;
        }
    }
    return JSON.parse(JSON.stringify(result));
}
function orderJsonOptionToArr(obj: {[key: string]: ToJsonOptions}) {
    let result: {propertyKey: string; options: ToJsonOptions}[] = [];
    for(let key in obj) {
        result.push({
            propertyKey: key,
            options: obj[key]
        });
    }
    return result.sort((a, b) => (b.options.parsePriority || 0) - (a.options.parsePriority || 0));
}
export function objTransformToClass(cls: Object, obj: Object) {
    let mapArr = orderJsonOptionToArr(cls.constructor.prototype.__TO_JSON_MAP__);
    for(let opt of mapArr) {
        // console.log(opt.propertyKey,obj.hasOwnProperty(opt.propertyKey), opt.options.ignore !== true)
        if (obj.hasOwnProperty(opt.propertyKey) && opt.options.ignore !== true) {
            if(opt.options.toCls) {
                // @ts-ignore
                cls[opt.options.name] = opt.options.toCls(cls, obj[opt.propertyKey]);
            } else {
                // @ts-ignore
                cls[opt.options.name] = obj[opt.propertyKey];
            }
        }
    }
    return cls;
}